from flask import Flask, request, jsonify, render_template, send_from_directory
from flask_cors import CORS
from models import db, Prompt
from config import Config
from datetime import datetime
import json
import os
import threading
import time
from apscheduler.schedulers.background import BackgroundScheduler
import requests

app = Flask(__name__)
app.config.from_object(Config)

# 初始化扩展
db.init_app(app)
CORS(app)

# 创建数据库表
with app.app_context():
    db.create_all()

# 全局变量存储Chrome插件数据
chrome_data_cache = []
last_sync_time = None

def sync_chrome_data():
    """从Chrome插件同步数据"""
    with app.app_context():
        global chrome_data_cache, last_sync_time
        
        try:
            print(f"[{datetime.now()}] 开始同步Chrome数据...")
            print(f"[{datetime.now()}] 缓存中有 {len(chrome_data_cache)} 条记录")
            
            # 获取同步前的记录数量
            before_count = Prompt.query.count()
            print(f"[{datetime.now()}] 同步前数据库中有 {before_count} 条记录")
            
            sync_count = 0
            chrome_ids = set()  # 记录Chrome端发送的所有ID
            
            for i, chrome_prompt in enumerate(chrome_data_cache):
                print(f"[{datetime.now()}] 处理第 {i+1} 条记录: {chrome_prompt}")
                
                chrome_id = chrome_prompt.get('id')
                if not chrome_id:
                    print(f"[{datetime.now()}] 跳过无效记录（缺少ID）: {chrome_prompt}")
                    continue
                
                chrome_ids.add(str(chrome_id))
                    
                existing_prompt = Prompt.get_by_chrome_id(chrome_id)
                
                if existing_prompt:
                    # 更新现有记录
                    print(f"[{datetime.now()}] 更新现有记录 ID: {chrome_id}")
                    existing_prompt.from_chrome_data(chrome_prompt)
                    sync_count += 1
                else:
                    # 创建新记录
                    print(f"[{datetime.now()}] 创建新记录 ID: {chrome_id}")
                    new_prompt = Prompt()
                    new_prompt.from_chrome_data(chrome_prompt)
                    db.session.add(new_prompt)
                    sync_count += 1
            
            # 检查是否有Chrome端没有发送但服务器端存在的记录
            # 这些记录可能是Chrome端数据丢失导致的，我们保留它们
            all_server_prompts = Prompt.query.all()
            server_chrome_ids = {prompt.chrome_id for prompt in all_server_prompts}
            missing_in_chrome = server_chrome_ids - chrome_ids
            
            if missing_in_chrome:
                print(f"[{datetime.now()}] 发现Chrome端缺失的记录: {missing_in_chrome}")
                print(f"[{datetime.now()}] 这些记录将保留在服务器端，不会被删除")
            
            db.session.commit()
            last_sync_time = datetime.utcnow()
            
            # 获取同步后的记录数量
            after_count = Prompt.query.count()
            print(f"[{datetime.now()}] 同步完成，处理了 {sync_count} 条记录")
            print(f"[{datetime.now()}] 同步后数据库中共有 {after_count} 条记录")
            
            if after_count < before_count:
                print(f"[{datetime.now()}] ⚠️ 警告：记录数量减少了 {before_count - after_count} 条")
            elif after_count > before_count:
                print(f"[{datetime.now()}] ✅ 新增了 {after_count - before_count} 条记录")
            else:
                print(f"[{datetime.now()}] ✅ 记录数量保持不变")
            
        except Exception as e:
            print(f"[{datetime.now()}] 同步失败: {str(e)}")
            import traceback
            traceback.print_exc()
            db.session.rollback()

# 配置定时任务
scheduler = BackgroundScheduler()
scheduler.add_job(
    func=sync_chrome_data,
    trigger="interval",
    seconds=app.config['SYNC_INTERVAL'],
    id='chrome_sync_job'
)
scheduler.start()

@app.route('/')
def index():
    """主页"""
    return render_template('index.html')

@app.route('/api/prompts', methods=['GET'])
def get_prompts():
    """获取提示词列表"""
    try:
        page = request.args.get('page', 1, type=int)
        per_page = request.args.get('per_page', 16, type=int)
        search = request.args.get('search', '', type=str)
        favorite = request.args.get('favorite', 'false').lower() in ('true', '1', 'yes')
        favorites_only = request.args.get('favorites_only', 'false').lower() in ('true', '1', 'yes')
        
        # 兼容两种参数名
        if favorite:
            favorites_only = True
        
        print(f"[{datetime.now()}] 获取提示词列表请求 - page: {page}, per_page: {per_page}, search: '{search}', favorites_only: {favorites_only}")
        
        # 首先检查数据库中的总记录数
        total_count = Prompt.query.count()
        print(f"[{datetime.now()}] 数据库中总记录数: {total_count}")
        
        # 构建查询
        query = Prompt.query
        
        if favorites_only:
            query = query.filter_by(is_favorite=True)
            print(f"[{datetime.now()}] 应用收藏过滤")
        
        if search:
            # 使用模糊搜索（支持前后模糊匹配）
            search_pattern = f"%{search}%"
            query = query.filter(Prompt.text.like(search_pattern))
            print(f"[{datetime.now()}] 应用模糊搜索过滤: '{search}'")
        
        # 检查过滤后的记录数
        filtered_count = query.count()
        print(f"[{datetime.now()}] 过滤后记录数: {filtered_count}")
        
        # 分页
        pagination = query.order_by(Prompt.updated_at.desc()).paginate(
            page=page, per_page=per_page, error_out=False
        )
        
        print(f"[{datetime.now()}] 分页结果 - total: {pagination.total}, pages: {pagination.pages}, items: {len(pagination.items)}")
        
        prompts = [prompt.to_dict() for prompt in pagination.items]
        
        return jsonify({
            'success': True,
            'data': {
                'prompts': prompts,
                'pagination': {
                    'page': page,
                    'per_page': per_page,
                    'total': pagination.total,
                    'pages': pagination.pages,
                    'has_next': pagination.has_next,
                    'has_prev': pagination.has_prev
                }
            }
        })
        
    except Exception as e:
        print(f"[{datetime.now()}] 获取提示词列表时发生错误: {str(e)}")
        import traceback
        traceback.print_exc()
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

@app.route('/api/prompts', methods=['POST'])
def create_prompt():
    """创建新提示词"""
    try:
        data = request.get_json()
        
        if not data or not data.get('text'):
            return jsonify({
                'success': False,
                'error': '提示词内容不能为空'
            }), 400
        
        # 检查是否已存在相同的Chrome ID
        chrome_id = data.get('chrome_id')
        if chrome_id and Prompt.get_by_chrome_id(chrome_id):
            return jsonify({
                'success': False,
                'error': '该提示词已存在'
            }), 409
        
        prompt = Prompt()
        prompt.from_chrome_data(data)
        
        db.session.add(prompt)
        db.session.commit()
        
        return jsonify({
            'success': True,
            'data': prompt.to_dict()
        }), 201
        
    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

@app.route('/api/prompts/<int:prompt_id>', methods=['GET'])
def get_prompt(prompt_id):
    """获取单个提示词"""
    try:
        prompt = Prompt.query.get_or_404(prompt_id)
        
        return jsonify({
            'success': True,
            'data': prompt.to_dict()
        })
        
    except Exception as e:
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

@app.route('/api/prompts/<int:prompt_id>', methods=['PUT'])
def update_prompt(prompt_id):
    """更新提示词"""
    try:
        prompt = Prompt.query.get_or_404(prompt_id)
        data = request.get_json()
        
        if not data:
            return jsonify({
                'success': False,
                'error': '请求数据不能为空'
            }), 400
        
        # 更新字段
        if 'text' in data:
            prompt.text = data['text']
        if 'is_favorite' in data:
            prompt.is_favorite = data['is_favorite']
        if 'image_data' in data:
            prompt.image_data = data['image_data']
        
        prompt.updated_at = datetime.utcnow()
        prompt.last_synced = datetime.utcnow()
        
        db.session.commit()
        
        return jsonify({
            'success': True,
            'data': prompt.to_dict()
        })
        
    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

@app.route('/api/prompts/<int:prompt_id>', methods=['DELETE'])
def delete_prompt(prompt_id):
    """删除提示词"""
    try:
        prompt = Prompt.query.get_or_404(prompt_id)
        
        db.session.delete(prompt)
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': '删除成功'
        })
        
    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

@app.route('/api/sync/last_update', methods=['GET'])
def get_last_sync_time():
    """获取最新的同步时间"""
    try:
        # 获取数据库中最新记录的更新时间
        latest_prompt = Prompt.query.order_by(Prompt.last_synced.desc()).first()
        if latest_prompt and latest_prompt.last_synced:
            # 确保返回UTC时间格式，带Z后缀
            last_sync_time = latest_prompt.last_synced.isoformat() + 'Z'
        else:
            last_sync_time = None
            
        return jsonify({
            'success': True,
            'last_sync_time': last_sync_time
        })
    except Exception as e:
        print(f"[{datetime.now()}] 获取最新同步时间失败: {str(e)}")
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

@app.route('/api/sync', methods=['POST'])
def sync_from_chrome():
    """从Chrome插件同步数据"""
    global chrome_data_cache
    
    try:
        data = request.get_json()
        print(f"[{datetime.now()}] 收到同步请求")
        
        if not data or 'prompts' not in data:
            print(f"[{datetime.now()}] 数据格式错误: {data}")
            return jsonify({
                'success': False,
                'error': '数据格式错误'
            }), 400
        
        chrome_prompts = data['prompts']
        last_sync_time = data.get('last_sync_time')
        
        print(f"[{datetime.now()}] 准备同步 {len(chrome_prompts)} 条记录，上次同步时间: {last_sync_time}")
        
        # 如果没有上次同步时间，执行全量同步
        if not last_sync_time:
            print(f"[{datetime.now()}] 执行全量同步")
            chrome_data_cache = chrome_prompts
            sync_chrome_data()
        else:
            # 执行增量同步
            print(f"[{datetime.now()}] 执行增量同步")
            chrome_data_cache = chrome_prompts
            sync_chrome_data()
        
        # 检查数据库中的记录数量
        total_count = Prompt.query.count()
        print(f"[{datetime.now()}] 同步后数据库中共有 {total_count} 条记录")
        
        return jsonify({
            'success': True,
            'message': f'同步成功，处理了 {len(chrome_prompts)} 条记录',
            'total_count': total_count
        })
        
    except Exception as e:
        print(f"[{datetime.now()}] 同步过程中发生错误: {str(e)}")
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

@app.route('/api/recover', methods=['POST'])
def recover_missing_data():
    """恢复Chrome端丢失的数据"""
    try:
        data = request.get_json()
        if not data or 'chrome_ids' not in data:
            return jsonify({
                'success': False,
                'error': '数据格式错误'
            }), 400
        
        chrome_ids = set(str(id) for id in data['chrome_ids'])
        print(f"[{datetime.now()}] Chrome端请求恢复数据，Chrome端ID: {chrome_ids}")
        
        # 获取服务器端的所有记录
        all_server_prompts = Prompt.query.all()
        server_chrome_ids = {prompt.chrome_id for prompt in all_server_prompts}
        
        # 找出Chrome端缺失的记录
        missing_ids = server_chrome_ids - chrome_ids
        print(f"[{datetime.now()}] 发现缺失的记录: {missing_ids}")
        
        # 获取缺失的记录数据
        missing_prompts = []
        for missing_id in missing_ids:
            prompt = Prompt.query.filter_by(chrome_id=missing_id).first()
            if prompt:
                missing_prompts.append(prompt.to_dict())
        
        print(f"[{datetime.now()}] 准备返回 {len(missing_prompts)} 条缺失记录")
        
        return jsonify({
            'success': True,
            'missing_prompts': missing_prompts,
            'count': len(missing_prompts)
        })
        
    except Exception as e:
        print(f"[{datetime.now()}] 恢复数据失败: {str(e)}")
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

@app.route('/api/stats', methods=['GET'])
def get_stats():
    """获取统计信息"""
    try:
        total_count = Prompt.query.count()
        favorite_count = Prompt.query.filter_by(is_favorite=True).count()
        
        return jsonify({
            'success': True,
            'data': {
                'total_count': total_count,
                'favorite_count': favorite_count,
                'last_sync': last_sync_time.isoformat() if last_sync_time else None
            }
        })
        
    except Exception as e:
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

@app.route('/api/files/<filename>')
def serve_file(filename):
    """提供静态文件服务"""
    try:
        return send_from_directory('files', filename)
    except Exception as e:
        return jsonify({
            'success': False,
            'error': f'文件不存在: {filename}'
        }), 404

@app.route('/api/files/original_images/<filename>')
def serve_original_image(filename):
    """提供原图文件服务"""
    try:
        return send_from_directory('files/original_images', filename)
    except Exception as e:
        return jsonify({
            'success': False,
            'error': f'原图文件不存在: {filename}'
        }), 404

@app.route('/api/export', methods=['GET'])
def export_prompts():
    """导出提示词数据"""
    try:
        favorites_only = request.args.get('favorites_only', False, type=bool)
        
        if favorites_only:
            prompts = Prompt.get_favorites()
        else:
            prompts = Prompt.query.order_by(Prompt.updated_at.desc()).all()
        
        # 转换为CSV格式
        csv_data = "id,chrome_id,text,source,is_favorite,created_at,updated_at\n"
        
        for prompt in prompts:
            # 处理文本中的引号，避免CSV格式错误
            text_escaped = prompt.text.replace('"', '""')
            csv_data += f'"{prompt.id}","{prompt.chrome_id}","{text_escaped}","{prompt.source}","{prompt.is_favorite}","{prompt.created_at}","{prompt.updated_at}"\n'
        
        return csv_data, 200, {
            'Content-Type': 'text/csv',
            'Content-Disposition': 'attachment; filename=prompts.csv'
        }
        
    except Exception as e:
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

if __name__ == '__main__':
    try:
        app.run(
            host=app.config['API_HOST'],
            port=app.config['API_PORT'],
            debug=True
        )
    except KeyboardInterrupt:
        print("正在关闭服务器...")
        scheduler.shutdown()
